package com.wordsay.analyer.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

import com.wordsay.analyer.Analyer;
import com.wordsay.common.Constant;
import com.wordsay.context.Context;
import com.wordsay.entity.HotItem;
import com.wordsay.entity.PDialogAnalystResult;
import com.wordsay.entity.People;
import com.wordsay.entity.PersonDialog;
import com.wordsay.entity.PersonSimilarResult;
import com.wordsay.util.FormulaUtil;

/**
 * person similare analyst
 * @author squirrelrao
 *
 */
public class PersonSimilarAnayler implements Analyer {

	@Override
	public Object execute(Object target) throws Exception {
		
		  List<PersonSimilarResult> results = new ArrayList<PersonSimilarResult>();
		  
	      List<PersonDialog> personDialogs = (List<PersonDialog>)target;
	      People self = Context.getInstance().getSelf();
	      
	      for(int i = 0; i < personDialogs.size(); i++){
	    	  
	    	  PDialogAnalystResult personAResult = (PDialogAnalystResult)personDialogs.get(i).getAnalystResult();	    	  
	    	  
	    	  for(int j = 1; j < personDialogs.size(); j++){
	    		  
		    	  PDialogAnalystResult personBResult = (PDialogAnalystResult)personDialogs.get(j).getAnalystResult();
	    	 
		    	  PersonSimilarResult similarResult = new PersonSimilarResult(personAResult.getChatPeopleName(),personBResult.getChatPeopleName());
		    	  		    	  
		    	  if(results.contains(similarResult) || personAResult.getChatPeopleName().trim().equals(personBResult.getChatPeopleName().trim())){
		    		  continue;
		    	  }
		    	  
		    	  //计算两个人的相似度
		    	  this.computePersonSimilar(similarResult, personAResult, personBResult);
		    	 // if(similarResult.getSimilarRate() == 0){
		    		//  continue;
		    	  //}
		    	  results.add(similarResult);
	    	  }
	    	  
	    	  
	      }
	      
	      return results;     
	}
	
	
	/**
	 * compute the similar between two people
	 * @param similarResult
	 * @param personAResult
	 * @param personBResult
	 */
	private void computePersonSimilar(PersonSimilarResult similarResult,PDialogAnalystResult personAResult,PDialogAnalystResult personBResult){
		
		 List<HotItem> similarWords = this.findSimilarWords(personAResult, personBResult);
		 		 
		 if(similarWords.size() == 0){
			 similarResult.setSimilarRate(0);
			 return;
		 }
		 
		 //compute similar word rate
		 double similarWordRate = FormulaUtil.computeSimilarWordRate(similarWords.size(), personAResult.getHotWords().size(),personBResult.getHotWords().size());
		 similarResult.setSimilarWordRate(similarWordRate);
		 
		 //compute the vecotors: A and B
		 List<HotItem> vectorA = this.getSimilarWordsVector(personAResult, similarWords);
		 List<HotItem> vectorB = this.getSimilarWordsVector(personBResult, similarWords);
		 
		 similarResult.setVectorA(vectorA);
		 similarResult.setVectorB(vectorB);
		 
		 double similarRate = FormulaUtil.computelinearWeigthSimilar(similarWordRate,vectorA, vectorB);
		 similarResult.setSimilarRate(similarRate);
	}
	
	/**
	 * get similar words vector
	 * @param personAResult
	 * @param similarWords
	 * @return
	 */
	private List<HotItem> getSimilarWordsVector(PDialogAnalystResult personResult,List<HotItem> similarWords){
	
		List<HotItem> vector = new ArrayList<HotItem>();
		
		BigDecimal totalFrequency = new BigDecimal(personResult.getWordsCount());
		
		List<HotItem> hotWords = personResult.getHotWords();
		if(personResult.getHotWords().size() == 0){
			return vector;
		}
		
		
		for(int i = 0; i < similarWords.size(); i++){
			
			HotItem word = similarWords.get(i);
							
			int indexOf = hotWords.indexOf(word);
		    HotItem item = new HotItem(word.getName(),-1);
		    
		    BigDecimal rate = (new BigDecimal(indexOf + 1)).divide(new BigDecimal(hotWords.size()),Constant.DIVIDE_SCALE,RoundingMode.HALF_UP);
		    rate = rate.negate().add(new BigDecimal(1));
		    
			if(rate.doubleValue() == 0){
				rate = new BigDecimal(0.1);
			}
			item.setHotRate(rate); 	
		    vector.add(item);
		}
		
		return vector;
	}
	
	
	/**
	 * find the similar words between two people's words
	 * @param personAResult
	 * @param personBResult
	 * @return
	 */
	private List<HotItem> findSimilarWords(PDialogAnalystResult personAResult,PDialogAnalystResult personBResult){
		
		List<HotItem> similarWords = new ArrayList<HotItem>();
		
		for(int i = 0; i < personAResult.getHotWords().size();i++){
			
			HotItem item = personAResult.getHotWords().get(i);
			
			if(personBResult.getHotWords().contains(item)){
				similarWords.add(item);
			}
		}
		
		return similarWords;
	}
	
	
}
